﻿

using System;
using System.Collections.Generic;
using UnityEngine;

namespace Assets.Scripts.DL.Enemy.BaseClass.FSM {
	/// <summary>
	/// 敌人的状态机框架和Player稍有不同，重写一遍
	/// </summary>
	/// <typeparam name="StateType"></typeparam>
	public abstract class EnemyState<StateType> {
		public StateType StateName { get; private set; }

		public EnemyState<StateType> CurState { get; set; } = null;

		//The conditions of transite to the same level state or fsm
		public Dictionary<StateType, Func<bool>> TransitionsTo { get; private set; } = new Dictionary<StateType, Func<bool>>();

		// Condition of Transite from other state to this,
		// usually used by a superFsm to decide which state to start
		public Func<bool> ConditionToSelf { get; private set; }

		public EnemyState(StateType stateName) {
			StateName = stateName;
			TransitionsTo = new Dictionary<StateType, Func<bool>>();
		}

		public abstract void Enter();

		public abstract void Update();

		public abstract void Exit();

		//写成public可以在复用的时候不修改已经写好的状态类，直接在外面添加条件
		public void AddConditionToSelf(Func<bool> condition) {
			ConditionToSelf += condition;
		}

		public void AddNewTransition(StateType state, Func<bool> condition) {

#if UNITY_EDITOR
			if (TransitionsTo.ContainsKey(state)) {
				Debug.Log($"The New State:{state} already In Transition List.");
				return;
			}
#endif
			TransitionsTo.Add(state, condition);
		}

		//		protected void AddNewTrasitionCondition(StateType state, Func<bool> condition) {

		//#if UNITY_EDITOR
		//			if (!TransitionsTo.ContainsKey(state)) {
		//				Debug.Log($"The State:{state} not In Transition List.");
		//				return;
		//			}
		//#endif
		//			TransitionsTo[state] += condition;
		//		}

		//		protected void MinusTransitionCon(StateType state, Func<bool> condition) {
		//#if UNITY_EDITOR
		//			if (!TransitionsTo.ContainsKey(state)) {
		//				Debug.Log($"The State:{state} not In Transition List.");
		//				return;
		//			}
		//#endif
		//			TransitionsTo[state] = Delegate.Remove(TransitionsTo[state], condition) as Func<bool>;

		//		}

		protected bool IsZero(float value) => Mathf.Abs(value) < 0.01;

		protected bool AreSignsEqual<T1, T2>(T1 num1, T2 num2)
			where T1 : struct, IComparable, IFormattable, IConvertible
			where T2 : struct, IComparable, IFormattable, IConvertible {
			int sign1 = Math.Sign(Convert.ToDouble(num1));
			int sign2 = Math.Sign(Convert.ToDouble(num2));

			return (sign1 == sign2);
		}
	}

}
